<template>
  <div
    v-if="!initializing"
    class="vc-component"
    :style="visual.parseStyle(currNode.currStyle)"
  >
    <div
      v-if="dataList.length > 0"
      class="vc-list-custom"
      :style="visual.parseStyle(compStyle)"
    >
      <div
        class="vc-list-custom-item"
        v-for="(data, index) in dataList"
        :key="index"
        @click="clickItem(data)"
      >
        <Component
          v-for="(child, index) in currNode.children"
          :key="index"
          :is="'vc-' + child.type"
          :node="tool.deepClone(child)"
          :inputParam="getInputParam(child, data)"
        />
      </div>
      <div
        v-if="dataPage && dataLoadMode === 'pagination'"
        class="vc-pagination"
      >
        <el-pagination
          :layout="`total, prev, pager, next
            ${showJumper ? ',jumper' : ''}
            ${showSizes ? ',sizes' : ''}`"
          :current-page="queryInfo.pageNumber"
          :page-size="queryInfo.pageSize"
          :total="page.totalRecord"
          :pager-count="pagerCount"
          @current-change="refreshPage"
          @size-change="handleSizeChange"
        />
      </div>
    </div>
    <div v-if="loading" class="loading">
      <div
        v-loading="true"
        element-loading-text="数据加载中..."
      ></div>
    </div>
    <div
      v-if="!loading && dataList.length === 0"
      class="vc-list-custom"
      :style="visual.parseStyle(currNode.currCompStyle)"
    >
      <div class="vc-list-empty">
        <div style="padding-top: 20px;text-align: center">{{emptyTips}}</div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, inject, getCurrentInstance, nextTick } from 'vue';
import visual from "@/visual/js/visual";
import EventHandler from "@/visual/js/event";
import emitter from "@/utils/bus";
import tool from "@/utils/tool";

const props = defineProps({
  node: Object
});

const initializing = ref(true);
const loading = ref(true);
const currNode = ref(props.node);
const compStyle = ref({});
const queryInfo = ref({
  pageNumber: 1,
  pageSize: 10
});
const hasPage = ref(true);
const page = ref({});
const dataList = ref([]);
const dataPage = ref(false);
const dataLoadMode = ref('pagination');
const showJumper = ref(false);
const showSizes = ref(false);
const pagerCount = ref(7);
const emptyTips = ref('无符合条件的数据');
const eventHandler = new EventHandler(
  inject('eventHandler', Function, true),
  getCurrentInstance(),
  currNode.value
);

const init = async(styleId) => {
  initializing.value = true;
  visual.initStyle(currNode.value, styleId);
  compStyle.value = currNode.value.currCompStyle || {};
  emptyTips.value = compStyle.value['empty-tips'] || '无符合条件的数据';

  const compData = currNode.value.compData || {};
  hasPage.value = true;
  dataPage.value = compData.dataPage || false;
  dataLoadMode.value = compData.dataLoadMode || 'pagination';
  showJumper.value = compData.showJumper || false;
  showSizes.value = compData.showSizes || false;
  pagerCount.value = compData.pagerCount || 7;
  if (dataPage.value) {
    queryInfo.value.pageSize = compData.dataPageSize || 20;
  } else {
    queryInfo.value.pageSize = compData.dataQueryTotal || 20;
  }

  if (dataLoadMode.value === 'bottom') {
    emitter.off('onReachBottom', onReachBottom);
    emitter.on('onReachBottom', onReachBottom);
  }
  await nextTick(() => initializing.value = false);
};

const clickItem = (row) => {
  eventHandler.trigger("点击条目事件", row);
};

const handleSizeChange = (pageSize) => {
  hasPage.value = true;
  queryInfo.value.pageSize = pageSize;
  refreshPage(1);
};

const refreshPage = async(pageNumber) => {
  queryInfo.value.pageNumber = pageNumber;
  findPage();
};

const findPage = tool.debounce(async() => {
  if (!hasPage.value) return;

  if (queryInfo.value.pageNumber === 1 || dataLoadMode.value !== 'bottom') {
    dataList.value = [];
  }
  loading.value = true;
  page.value = await visual.loadData(
    currNode.value.compData,
    eventHandler,
    getData(),
    currNode.value) || {};
  if (dataLoadMode.value === 'bottom') {
    if (page.value.data && page.value.data.length > 0) {
      dataList.value.push(...page.value.data);
    }
    if (!page.value.data
        || dataList.value.length >= page.value.totalRecord
        || page.value.data.length < queryInfo.value.pageSize) {
      hasPage.value = false;
    }
  } else {
    dataList.value = page.value.data || [];
  }
  await nextTick(() => loading.value = false);
});

const getInputParam = (child, data) => {
  const result = {};
  result[`list.${currNode.value.id}.row`] = data;
  if (child.type === 'container') {
    return result;
  } else {
    return visual.getInputParam(child, result);
  }
};

const getData = () => {
  return {
    ...queryInfo.value,
    inputParam: currNode.value.inputParam || {}
  };
};

const changeStyle = (styleId) => {
  init(styleId);
};

const refresh = async() => {
  initializing.value = true;
  hasPage.value = true;
  await refreshPage(1);
  await nextTick(() => initializing.value = false);
};

const onReachBottom = () => {
  queryInfo.value.pageNumber++;
  findPage();
};

onMounted(async() => {
  await init();
  await refreshPage(1);
  await eventHandler.trigger('初始化事件');
});

onUnmounted(() => {
  eventHandler.unregister();
  emitter.off('onReachBottom', onReachBottom);
});

defineExpose({ init, getData, changeStyle, refresh });
</script>

<style scoped>
.vc-pagination {
  margin: 10px 0;
  padding: 5px;
  width: 100%;
  display: flex;
  flex-direction: row;
  place-content: flex-end;
  background: #ffffff;
  border-radius: 5px;
  overflow: auto;
}
</style>